﻿//指针和数组的面试题

//3tips
//#include<stdio.h>
//int main()
//{
//	//一维数组
//	int a[] = { 1,2,3,4 };
//
//	printf("%d\n", sizeof(a));//✔
//	//sizeof(数组名）表示整个数组，数组名a单独放在sizeof内部，计算的是整个数组的大小单位是字节，16字节
//	//4个元素，每个元素是int类型（4个字节），16个字节
//	//16
//	printf("%d\n", sizeof(a + 0));
//	//sizof(a+0),数组名a并非单独放在sizeof内部，也没有&，a表示数组首元素的地址，+0还是首元素的地址，地址无论何种类型，大小都是4/8个字节
//	//4/8字节
//	printf("%d\n", sizeof(*a));
//	//sizeof(*a),数组名a并非单独放在sizeof内部，也没有&，a表示数组首元素的地址，*a表示解引用首元素的地址即找到第一个元素，就是1，一个整型元素的大小就是4个字节。
//	//4字节
//	//*a==*(a+0)==a[0]
//
//
//
//	printf("%d ", sizeof(a + 1));//地址++和*地址++✔
//	//sizeof(a+1),数组名a并非单独放在sizeof内部，也没有&,a表示首元素的地址，a+1表示第二个元素的地址，地址无论是何种类型，大小都是4/8个字节
//	//4/8个字节--8个字节（64位）
//	//a+1 == &a[1] 是第二个元素的地址
//	//指向哪里？
//	printf("%d\n", sizeof(*a + 1));
//	//*a是首元素地址解引用为首元素，+1也好，++也罢。都只是往后移动一位4个字节，并没有说1+1=2 赋值这样，计算第二个元素的地址
//	//4个字节
//	
//
//
//	printf("%d\n", sizeof(a[1]));
//	//sizeof(a[1]),a[1]下标引用操作符，数组的下标从0开始，所以a[1]指的是第二个元素2，一个整型元素的大小是4个字节
//	//4个字节
//	printf("%d\n", sizeof(&a));//✔
//	//sizeof(&a),a表示整个数组，&a就是把整个数组的地址都取出来，无论怎样还是表示地址，地址无论是何种类型，大小都是4/8个字节
//	//4/8个字节
//	//数组的地址 和 数组首元素的地址 的本质区别是类型的区别 并非大小的区别
//	//a --- int* --指针--          int*p =a;解引用访问的是一个整型的大小
//	//&a --- int(*)[4]--指针数组--       int*p[4]= &a;解引用访问的是一个数组的大小
//	//但是对于p来说，都是存放一个地址，数组首元素的地址也好，整个数组的地址也好，都是一个地址，大小都是4/8个字节
//
//	printf("%d\n", sizeof(*&a));
//	//sizeof(*&a),a表示整个数组，&a就是把整个数组的地址都取出来，*&a就是把整个数组的地址都解引用，表示整个数组的元素，16个字节
//	//16字节
//	//*和&抵消了
//
//	printf("%d\n", sizeof(&a + 1));//✔
//	//sizeof(&a+1),a表示整个数组的元素，&a就是把整个数组的地址都取出来，+1就是跳过一整个a数组的元素，指向跳过后的地址处，
//	//无论怎样还是表示地址，地址无论是何种类型，大小都是4/8个字节
//	//4/8个字节
//	//指向哪里？
//
//	printf("%d\n", sizeof(&a[0]));
//	//sizeof(&a[0]),操作符的优先级a先和[]，下标引操作符结合，得到元素1；再和&结合，得到1的地址。也就是首元素的地址。
//	//无论怎样还是表示地址，地址无论是何种类型，大小都是4/8个字节
//	//4/8个字节
//	printf("%d\n", sizeof(&a[0] + 1));
//	//sizeof(&a[0]+1),同上，得到首元素地址，+1得到第二个元素的地址。
//	//无论怎样还是表示地址，地址无论是何种类型，大小都是4/8个字节
//	//4/8个字节
//	//&a[1]
//	//&a[0]+1
//	//a+1
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%d\n", sizeof(arr));
//	printf("%d\n", sizeof(arr + 0));
//	printf("%d\n", sizeof(*arr));
//	printf("%d\n", sizeof(arr[1]));
//	printf("%d\n", sizeof(&arr));
//	printf("%d\n", sizeof(&arr + 1));
//	printf("%d\n", sizeof(&arr[0] + 1));
//
//	printf("%d\n", strlen(arr));
//	printf("%d\n", strlen(arr + 0));
//	printf("%d\n", strlen(*arr));
//	printf("%d\n", strlen(arr[1]));
//	printf("%d\n", strlen(&arr));
//	printf("%d\n", strlen(&arr + 1));
//	printf("%d\n", strlen(&arr[0] + 1));
//	return 0;
//}
//#include<stdio.h>
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };//6
//	printf("%d\n", sizeof(arr));//✔
//	//sizeof(arr),数组名arr单独放在sizeof内部，指的是整个数组，计算的是整个数组的元素，6个字节
//	printf("%d\n", sizeof(arr + 0));//✔
//	//sizeof(arr+0),arr指的是首元素地址，+0还是首元素地址，地址无论何种类型，大小就是4/8个字节
//	//arr是首元素的地址 == &arr[0].是地址就是4/8个字节
//	//char*
//	//指针变量的大小和类型无关，不管什么类型的指针变量，大小都是4/8个字节
//	//指针变量是用来存放地址的，地址存放需要多大空间，指针变量的大小就是几个字节。
//	//32位环境下，地址是32个二进制，需要4个字节，所以指针变量的大小就是几个字节
//	//32位环境下，地址是64个二进制，需要8个字节，所以指针变量的大小就是几个字节
//	//🆗🆗请不要在门缝里看指针，把指针看扁了。
//	printf("%d\n", sizeof(*arr));
//	//sizeof(*arr),arr指的是首元素地址，*arr是数组的第一个元素，1个字节
//	printf("%d\n", sizeof(arr[1]));
//	//数组第2个元素，数组的下标从0开始，1个字节
//	printf("%d\n", sizeof(&arr));//✔
//	//&arr是数组的地址，指的是整个数组的地址，数组指针，char(*p)[6]=地址无论何种类型，大小就是4/8个字节
//	printf("%d\n", sizeof(&arr + 1));
//	//&arr+1 是跳过数组后的地址，地址无论何种类型，大小就是4/8个字节
//	printf("%d\n", sizeof(&arr[0] + 1));
//	//第二个元素的地址，地址无论何种类型，大小就是4/8个字节
//	return 0;
//}



//strlen求字符串长度
//统计的是在字符串\0之前的出现的字符个数
//sizeof求字符串长度时
//统计的是包括\0和\0之前的出现的字符个数

//#include<stdio.h>
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };//6个没有\0
//	printf("%d\n", strlen(arr));
//	//arr指的是首元素的地址
//	//strlen从首元素往后计算字符的个数遇到\0停止，但是在此时内存中我们不知道\0在何处
//	// 此处求出应该是随机值
//	printf("%d\n", strlen(arr + 0));
//	//arr+0指的是首元素的地址。
//	//strlen从首元素往后计算字符的个数遇到\0停止，但是在此时内存中我们不知道\0在何处
//	// 此处求出应该是随机值
//	printf("%d\n", strlen(*arr));
//	//*arr指的是首元素。
//	//把'a'的ascll码值97 传给strlen,因为strlen只接受地址。
//	//所以站在strlen的角度上，认为97是一个地址，是非法地址，直接访问发生非法访问，所以会报错。err
//	printf("%d\n", strlen(arr[1]));
//	//arr[1]是首元素  'b'-98
//	//同上err
//	printf("%d\n", strlen(&arr));
//	//&arr是整个数组的地址，数值上和首元素地址一样。
//	//所以，strlen从首元素往后计算字符的个数遇到\0停止，但是在此时内存中我们不知道\0在何处
//	// 此处求出应该是随机值
//	printf("%d\n", strlen(&arr + 1));
//	//&arr+1,整个数组的地址+1，跳过整个数组，指向跳过整个数组之后的元素
//	// 整个数组的地址是字符数组指针类型,	// 而我们的strlen接收的是字符指针类型
//	// char(*)[6]                              const char*
//	//所以这里会发生类型转化
//
//	//那我们更加不知道在内存何处会遇到\0，所以随机值
//	printf("%d\n", strlen(&arr[0] + 1));
//	//&arr[0]+1,首元素地址+1，即指向第二个元素的地址。
//	//所以，strlen从第二个元素往后计算字符的个数遇到\0停止，但是在此时内存中我们不知道\0在何处
//	// 此处求出应该是随机值
//	return 0;
//}















//#include<stdio.h>
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%d\n", sizeof(arr));//7
//	//计算的是整个数组的大小包括\0
//	printf("%d\n", sizeof(arr + 0));//4/8
//	//sizeof计算的是一个变量所占空间的大小
//	//计算的是首元素地址的大小4/8
//	printf("%d\n", sizeof(*arr));//1
//	//计算的是首元素的大小1
//	printf("%d\n", sizeof(arr[1]));//1
//	//计算的是第二个元素的大小
//	printf("%d\n", sizeof(&arr));//4/8
//	//计算整个数组的地址4/8
//	printf("%d\n", sizeof(&arr + 1));//4/8
//	//计算跳过整个数组后指向的地址4/8
//	printf("%d\n", sizeof(&arr[0] + 1));//4/8
   // printf("%d\n", sizeof(arr + 1));
//	//计算跳过首元素地址指向第二元素的地址4/8
//	return 0;
//}


//#include<stdio.h>
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%d\n", strlen(arr));//6
//	//首元素的地址往后计算直到遇到\0停止
//	printf("%d\n", strlen(arr + 0));//6
//	//首元素的地址往后计算直到遇到\0停止
//	printf("%d\n", strlen(*arr));//'a'——97
//	//err
//	printf("%d\n", strlen(arr[1]));//'b'——98
//	//err
//	printf("%d\n", strlen(&arr));//6
//	//整个数组的地址在数值上 == 首元素地址 往后计算直到遇到\0停止
//	printf("%d\n", strlen(&arr + 1));//随机值
//	//跳过整个数组后指向的地址，后面什么时候遇到\0未知，随机值
//	printf("%d\n", strlen(&arr[0] + 1));//5
//	printf("%d\n", strlen(arr + 1));//5
//	//指向第二个元素的地址，往后计算直到遇到\0停止
//	return 0;
//}
//
//#include<stdio.h>
//int main()
//{
//	char arr[] = "abcdef";
//	char* p = "abcdef";
//	printf("%d\n", sizeof(p));//4/8
//	//p是字符指针，存放的是地址，大小是4/8
//	//p指的是首元素的地址
//	printf("%d\n", sizeof(arr));//7
//
//	printf("%d\n", sizeof(p + 1));//4/8
//	//p+1，计算的是第二个元素的地址，大小4/8
//
//	printf("%d\n", sizeof(*p));//1
//	//首元素'a',指针解引用，看指针的类型，char*,是访问1个字节
//	printf("%d\n", sizeof(p[0]));//1
//
//	printf("%d\n", sizeof(&p));//4/8
//	printf("%d\n", sizeof(&p + 1));//4/8
//	printf("%d\n", sizeof(&p[0] + 1));//4/8
//	return 0;
//}

//
//#include<stdio.h>
//int main()
//{
//	char arr[] = "abcdef";
//	char* p = "abcdef";
//	printf("%d\n", strlen(p));//6
//	printf("%d\n", strlen(p + 1))//5
//	printf("%d\n", strlen(*p));//err
//	printf("%d\n", strlen(p[0]));//err
//	printf("%d\n", strlen(&p));//随机值
//	printf("%d\n", strlen(&p + 1));//随机值
//	printf("%d\n", strlen(&p[0] + 1));//5
//	return 0;
//}



////二维数组
//#include<stdio.h>
//int main()
//{
//	int a[3][4] = { 0 };
//	printf("%zd\n", sizeof(a));//4*3*4=48
//	//二维数组名 单独放在sizeof内部中，计算的是整个数组的大小，单位是字节。
//	printf("%zd\n", sizeof(a[0][0]));//4
//	//第一行第一列的元素，计算一个元素的大小，整型，单位字节
//
//
//	printf("%zd\n", sizeof(a[0]));//16
//	//第一行的数组名 a[0]单独放在sizeof内部，计算的是整个第一行的大小，4*4=16
//	//a[0]就表示整个第一行这个一维数组，sizeof(a[0])计算的整个第一行这个一维数组的大小
//	printf("%zd\n", sizeof(a[0] + 1));//4/8
//	//第一行的数组名没有单独放在sizeof内部，也没有&，表示第一行首元素的地址
//	//也就是第一行第一个元素的地址 a[0]== &a[0][0]   a[0]+1== &a[0][1]
//	//+1表示第一行第二个元素的地址。
//	printf("%zd\n", sizeof(*(a[0] + 1)));//4
//	//*解引用，表示第二个元素
//
//
//
//	printf("%zd\n", sizeof(a + 1));//4/8
//	//a没有单独放在sizeof内部，
//	// 表示二维数组首元素地址，即第一行的地址,a的类型int(*)[4]---数组指针
//	// +1表示第二行的地址。
//	printf("%zd\n", sizeof(*(a + 1)));//4*4=16
//	//解引用，表示整个第二行的大小，整型4*4
//	//*（a+1) == a[1]
//	//sizeof(a[1]) --- a[1]表示第二行的数组名，单独放在sizeof内部，即计算的是整个第二行的大小
//
//	printf("%zd\n", sizeof(&a[0] + 1));//4/8
//	//a[0]表示第一行的数组名，&表示第一行的地址，类型是int(*)[4],
//	//+1表示第二行的地址,类型int(*)[4]
//	printf("%zd\n", sizeof(*(&a[0] + 1)));//16
//	//解引用，表示第二行的大小
//
//
//	printf("%zd\n", sizeof(*a));//16
//	//a并非单独放在sizeof内部，a表示二维数组首元素地址，即第一行的地址，
//	// 解引用表示第一行的大小
//	//*a == *(a+0) == a[0]
//
//	printf("%zd\n", sizeof(a[3]));//4/8
//	//与a[0]同一类型int * [4],整行的地址，4/8
//	//sizeof根据表达式的类型属性来计算大小的，并不会真正访问第四行，不会越界
//	//a[3]    a[0]
//	//int [4]     int[4]
//
//	return 0;
//}